package ASTInterpreter;

import stone.StoneException;
import stone.Symbols;


// 数组环境(区别于BasicEnv, 其使用字典来存储和索引变量)
// 局部环境下, 可以通过分析获取局部环境中变量的个数
// 因此可以指定ArrayEnv中数组的大小
// 以nest来嵌套查询或索引对应的环境(env)
// index则用于在values数组中索引变量



public class ArrayEnv implements Environment {
	
	protected Object[] values;  // 存放当前环境包含的变量
	protected Environment outer;  // 外层环境(env)
	
	public ArrayEnv(int size, Environment out) {
		values = new Object[size];
		outer = out;
	}
	
	public Symbols symbols() {
		throw new StoneException("no symbols");
	}
	
	public Object get(int nest, int index) {
		// 根据(环境)嵌套层数和下标来索引变量
		if (nest == 0) {
			return values[index];
		}
		else if (outer == null) {
			return null;
		}
		else {
			return ((ArrayEnv)outer).get(nest - 1, index);
		}
	}
	
	public void put(int nest, int index, Object value) {
		// 将变量value存入嵌套层为nest的环境env中, 存放位置为env的values数组的index位置
		if (nest == 0) {
			values[index] = value;
		}
		else if (outer == null) {
			throw new StoneException("no outer environment");
		}
		else {
			((ArrayEnv)outer).put(nest - 1, index, value);
		}
	}

	@Override
	public void put(String name, Object value) {
		error(name);
	}

	@Override
	public Object get(String name) {
		error(name);
		return null;
	}

	@Override
	public void putNew(String name, Object value) {
		error(name);
	}

	@Override
	public Environment where(String name) {
		error(name);
		return null;
	}

	@Override
	public void setOuter(Environment e) {
		outer = e;
	}
	
	private void error(String name) {
		throw new StoneException("cannot access by name: " + name);
 	}

}
